/**
 * @file 	event_mng.c
 * @brief   事件管理
 * @author 	Liuwei
 * @version 1.0.1
 * @date 	2023-04-18
 * 
 * @copyright Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD
 * 
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version   <th>Author   <th>Description
 * <tr><td>2023-04-18 <td>1.0.1     <td>Liuwei   <td>首次创建
 * </table>
 */
/** Includes -----------------------------------------------------------------*/
#include "event_mng.h"
#include "If_rtc.h"
#include "diagnosis.h"
#include "queue_event.h"
#include "If_rtc.h"
#include "var_mng.h"
#include "param_mng.h"
#include "cfg_prj.h"
#include "If_nvm.h"
#include "If_di.h"
#include "mcu_type.h"
#include "sample.h"
#include "If_do.h"
/** Private typedef ----------------------------------------------------------*/
#pragma pack(1)
typedef struct 
{
	uint8_t  chk_flag;
	uint16_t now_idx; /* 当前记录序号 */
	uint16_t re_idx;  /* 当前序号补码 */

	uint16_t back_now_idx; /*备份：当前记录序号 */
	uint16_t back_re_idx;  /*备份：当前记录补码 */
	uint8_t  end_code;
}event_idx_type;
#pragma pack()

/** Private macro/define -----------------------------------------------------*/

/** Private variables --------------------------------------------------------*/
/** @brief 事件RAM缓冲区*/
static event_data_type ram_event_buf[EVENT_RAM_BUF_SIZE] = {0};   
static queue_type queue_event_obj = {0};     
static event_idx_type event_idx_obj = {0};
/** Global variables ---------------------------------------------------------*/

/** Local functions ----------------------------------------------------------*/
static event_data_type event_get_data(uint8_t evt_id);
static uint16_t event_read_idx_form_nvm(void);
static void event_set_idx(uint16_t idx);
static uint8_t event_write_idx_to_nvm(void);
/** ------------------------------------------------------------------------- *
  *                             Global function
 ** ------------------------------------------------------------------------- */
/**
 * @brief 事件初始化
 */
void event_init(void)
{
    queue_init(&queue_event_obj , EVENT_RAM_BUF_SIZE , ram_event_buf);
	
	event_read_idx_form_nvm();
}

/**
 * @brief 清楚所有事件记录
 */
void event_clr_all(void)
{
	event_set_idx(0); 
	
	event_write_idx_to_nvm();
}

/**
 * @brief  更新RAM历史记录到NVM区域
 * @return void 
 */
uint8_t event_write_to_nvm(void)
{
	uint16_t now_idx = 0;
	uint32_t save_addr = 0;
	event_data_type event_msg = {0};
	uint8_t ret = FALSE;
	
	if(FALSE == queue_is_empty(queue_event_obj))
	{
		queue_out_fifo(&queue_event_obj , &event_msg);
		
		now_idx = event_idx_obj.now_idx % EVENT_MAX_SIZE;

		save_addr = now_idx * EVENT_DATA_SIZE + EVENT_RCD_ADDR;

		ret = If_nvm_save_data(save_addr , (uint8_t *)&event_msg , EVENT_DATA_SIZE);
        
		event_idx_obj.now_idx = event_idx_obj.now_idx + 1;

		if(event_idx_obj.now_idx >= EVENT_MAX_SIZE)
		{
			event_idx_obj.now_idx = EVENT_MAX_SIZE + event_idx_obj.now_idx % EVENT_MAX_SIZE;
		}

		event_set_idx(event_idx_obj.now_idx); 

		event_write_idx_to_nvm();
	}
	
	return ret;
}

/**
 * @brief  读取现在历史记录位置
 * @return uint16_t:历史记录位置
 */
uint16_t event_get_index(void)
{
	return (event_idx_obj.now_idx % EVENT_MAX_SIZE);
}

/**
 * @brief  读取当前已存储的数量
 * @return uint16_t 存储数量 
 */
uint16_t event_get_use_num(void)
{
	return event_idx_obj.now_idx > EVENT_MAX_SIZE ? EVENT_MAX_SIZE : event_idx_obj.now_idx;
}

/**
 * @brief  加载一条历史记录到SARM中 
 * @param  evt_id : 事件名称
 * @return 返回加载的状态 TURE : 成功，FLASE :失败
 */
uint8_t event_add_to_sram(uint8_t evt_id, uint16_t data ,uint16_t param)
{
	event_data_type event_msg = {0};

  	event_msg = event_get_data(evt_id);
	event_msg.name.now_val = data;
	event_msg.name.para_val = param;
    
	if(FALSE == queue_is_full(queue_event_obj))
    {
        queue_in_fifo(&queue_event_obj , event_msg);
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

/**
 * @brief  从nvm读取一条历史记录到SRAM中
 * @param  evt_id : 事件名称
 * @return 返回读取的状态 TURE : 成功，FLASE :失败
 */
uint8_t event_read_event(uint16_t idx, event_data_type *pevt)
{
	uint8_t ret = 0;
	uint32_t nvm_addr = 0;
	
	event_data_type event_msg = {0};
	
	idx = (idx == 0 ? EVENT_MAX_SIZE - 1 : idx - 1);
	
	nvm_addr = idx * EVENT_DATA_SIZE + EVENT_RCD_ADDR;

	If_nvm_read_data(nvm_addr, (uint8_t *)&event_msg , EVENT_DATA_SIZE);
	
	*pevt = event_msg;
	
	return ret;
}

/** ------------------------------------------------------------------------- *
  *                          Local function
 ** ------------------------------------------------------------------------- */
/**
 * @brief  获取一条历史事件数据
 * @param  evt_id
 * @return event_data_type 事件数据
 */
static event_data_type event_get_data(uint8_t evt_id)
{
    event_data_type event_msg = {0};
	uint8_t i = 0;
	uint8_t soh = 0;
	
	rtc_data_type now_time = {0};
	
	If_rtc_read_time(&now_time);
	
	event_msg.name.addr = var_get_data(VAR_ID_SELF_ADDR);
	event_msg.name.year = now_time.year - 2000;
	event_msg.name.month = now_time.month;
	event_msg.name.day = now_time.day;
	event_msg.name.hour = now_time.hour;
	event_msg.name.min = now_time.min;  
	event_msg.name.sec = now_time.sec;  
	event_msg.name.event_id = evt_id;
    event_msg.name.batt_volt = var_get_data(VAR_ID_BATT_VOLT);
	event_msg.name.bus_curr = var_get_data(VAR_ID_BUS_CURR);
	event_msg.name.soc = var_get_data(VAR_ID_DISP_SOC) * 0.01;
	soh = param_get_data(PAR_ID_SOH);
	if(soh > 100)
		soh = 100;
	event_msg.name.soh = soh;
	event_msg.name.mos_state.byte = var_get_data(VAR_ID_MOS_STATE);
	/*新增20241029*/
	if(If_do_get_out_state(DO_HOT_CTRL) == DO_OUT_ON)
		event_msg.name.mos_state.name.HOT_MOS = 1;
	if((If_do_get_out_state(DO_LIMIT_10A) == DO_OUT_ON) || (If_do_get_out_state(DO_LIMIT_5A) == DO_OUT_ON))
		event_msg.name.mos_state.name.LIMIT = 1;
	if(If_do_get_out_state(DO_RLY_SOCL) == DO_OUT_ON)
		event_msg.name.mos_state.name.RLY_SOC = 1;
	if(If_do_get_out_state(DO_RLY_FAULT) == DO_OUT_ON)
		event_msg.name.mos_state.name.RLY_FAULT = 1;
		
	event_msg.name.sys_state = var_get_data(VAR_ID_CURR_DR);
	event_msg.name.alm_msg.alm_word = diag_get_all_alarm();
	event_msg.name.prp_msg.prp_word = diag_get_all_prp();
    event_msg.name.full_cap = param_get_data(PAR_ID_FULL_CAP);
    event_msg.name.std_cap = param_get_data(PAR_ID_STD_CAP);
    event_msg.name.real_cap = var_get_data(VAR_ID_DISP_RCAP);
	event_msg.name.acc_chg_ah = (var_get_data(VAR_ID_ACC_CHG_AH_H) << 16) + var_get_data(VAR_ID_ACC_CHG_AH_L);
    event_msg.name.acc_dsg_ah = (var_get_data(VAR_ID_ACC_DSG_AH_H) << 16) + var_get_data(VAR_ID_ACC_DSG_AH_L);    
    event_msg.name.env_temp = var_get_data(VAR_ID_ENV_TEMP);  
	event_msg.name.mos_temp = var_get_data(VAR_ID_MOS_TEMP);  
	event_msg.name.cell_num = param_get_data(PAR_ID_CB_CELL_NUM);
	if(event_msg.name.cell_num >= CELL_MAX_NUM)
		event_msg.name.cell_num = CELL_MAX_NUM;
	for(i = 0; i < event_msg.name.cell_num;++ i)
	{
		event_msg.name.cell_buf[i] = var_get_data(VAR_ID_CELL_VOLT01 + i);
	}
 	event_msg.name.temp_num = param_get_data(PAR_ID_CB_TEMP_NUM);	
	for(i = 0; i < event_msg.name.temp_num; ++ i)
	{
		event_msg.name.temp_buf[i] = var_get_data(VAR_ID_CELL_TEMP01 + i) * 0.1;
	}
	event_msg.name.cycle = param_get_data(PAR_ID_CYCLE);

	return event_msg;
}

void event_test(void)
{
    static uint16_t cnt = 0;
    
    event_idx_obj.now_idx = 0;
    while(1)
    {
        event_add_to_sram(cnt , 100 , 100);
        
        event_write_to_nvm();
        
        if(++ cnt > 11)
            break;
    }
}

/** ------------------------------------------------------------------------- *
  *                              Local function
 ** ------------------------------------------------------------------------- */
/**
 * @brief  设置当前事件序号
 * @param  idx : 设置值
 */
static void event_set_idx(uint16_t idx)
{
	event_idx_obj.chk_flag = 0x5A;
	event_idx_obj.now_idx = idx;
	event_idx_obj.re_idx = ~idx;
	event_idx_obj.back_now_idx = idx;
	event_idx_obj.back_re_idx = ~idx;
	event_idx_obj.end_code = 0xA5;
}

/**
 * @brief  写入当前序号到非易失存储区
 */
static uint8_t event_write_idx_to_nvm(void)
{
	uint8_t ret = FALSE ; 

	ret = If_nvm_save_data(EVENT_IDX_ADDR, (uint8_t *)&event_idx_obj , 10);

	return ret;
}

/**
 * @brief  从非易失存储区读取当前序号值
 */
static uint16_t event_read_idx_form_nvm(void)
{
	uint8_t ret = 0;
	
	ret = If_nvm_read_data(EVENT_IDX_ADDR, (uint8_t *)&event_idx_obj , 10);

	if((ret == TRUE) && ((0x5A != event_idx_obj.chk_flag) || (0xA5 != event_idx_obj.end_code)))
	{
		event_set_idx(0);

		event_write_idx_to_nvm();
	}

	return event_idx_obj.now_idx;
}

/********** Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD *********/

